package com.sntk.organauthomanager.application.service;

import com.sntk.organauthomanager.application.dto.RoleCreator;
import com.sntk.organauthomanager.application.dto.RoleDTO;
import com.sntk.organauthomanager.domain.model.*;
import com.sntk.organauthomanager.domain.repository.OrganizationRepository;
import com.sntk.organauthomanager.domain.repository.ResourceRepository;
import com.sntk.organauthomanager.domain.repository.RoleRepository;
import com.sntk.organauthomanager.domain.repository.RoleResourceRepository;
import com.sntk.organauthomanager.infrastructure.exception.ObjectNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName: RoleApplicationService
 * @author: wgchao
 * @createTime: 2020/7/21 3:37 PM
 * @Description: TODO
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class RoleApplicationService {
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private OrganizationRepository organizationRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private RoleResourceRepository roleResourceRepository;
    @Autowired
    private ApplicationEventPublisher publisher;

    /**
     * 添加角色
     * @param institutionNumber
     * @param creator
     * @param operator
     */
    public void addRoleToOrgan(String institutionNumber, RoleCreator creator, String operator){
        Organization organization = organizationRepository.findByKey(institutionNumber);
        if(organization == null){
            throw new ObjectNotFoundException("所属机构不存在");
        }
        Role role = organization.addRole(creator.getRoleCode(), creator.getRoleName(), creator.getRemark());
        roleRepository.add(role, operator);
    }


    /**
     * 修改角色信息
     * @param roleDTO
     * @param operator
     */
    public void modifyRoleInfo(RoleDTO roleDTO, String operator){
        Role role = roleRepository.findByKey(new RoleIdentify(roleDTO.getInstitutionNumber(), roleDTO.getRoleCode()));
        if(role == null){
            throw new ObjectNotFoundException("角色不存在");
        }
        role.modifyRoleInfo(roleDTO.getRoleName(), roleDTO.getRemark(), roleDTO.isDisabled());
        roleRepository.add(role, operator);
    }

    /**
     * 删除角色
     * @param institutionNumber
     * @param roleCode
     * @param operator
     */
    public void removeRole(String institutionNumber, String roleCode, String operator){
        Role role = roleRepository.findByKey(new RoleIdentify(institutionNumber, roleCode));
        if(role == null){
            throw new ObjectNotFoundException("角色不存在");
        }
        roleRepository.delete(role.getRoleIdentify(), operator);

        //发送事件
        publisher.publishEvent(new RoleRemovedEvent(roleCode, institutionNumber, new Date(), operator));
    }

    /**
     * 为角色分配资源权限
     * @param institutionNumber
     * @param roleCode
     * @param marks
     */
    public void assignResourcesToRole(String institutionNumber, String roleCode, List<String> marks, String operator){
        Organization organization = organizationRepository.findByKey(institutionNumber);
        if(organization == null){
            throw new ObjectNotFoundException("角色所在机构不存在");
        }
        Role role = roleRepository.findByKey(new RoleIdentify(institutionNumber, roleCode));
        if(role == null){
            throw new ObjectNotFoundException("角色不存在");
        }
        List<Resource> resources = new ArrayList<>();
        if(marks!=null && !marks.isEmpty()){
            for(String mark : marks){
                Resource resource = resourceRepository.findByKey(mark);
                if(resource == null){
                    throw new ObjectNotFoundException("分配资源不存在");
                }
                resources.add(resource);
            }
        }
        RoleResource roleResource = new RoleResource(organization, role, resources);
        roleResourceRepository.add(roleResource, operator);
    }

    /**
     * 角色删除-删除角色资源关系
     * @param roleRemovedEvent
     */
    @EventListener
    public void removeUserRole(RoleRemovedEvent roleRemovedEvent){
        roleResourceRepository.removeByRole(new RoleIdentify(roleRemovedEvent.getInstitutionNumber(), roleRemovedEvent.getRoleCode()),
                roleRemovedEvent.getOperator());
    }
}
